//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.netflix.eureka.cluster;

import com.netflix.appinfo.ApplicationInfoManager;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.EurekaClientConfig;
import com.netflix.discovery.endpoint.EndpointUtils;
import com.netflix.discovery.endpoint.EndpointUtils.InstanceInfoBasedUrlRandomizer;
import com.netflix.eureka.EurekaServerConfig;
import com.netflix.eureka.registry.PeerAwareInstanceRegistry;
import com.netflix.eureka.resources.ServerCodecs;
import com.netflix.eureka.transport.JerseyReplicationClient;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Singleton
public class PeerEurekaNodes {
    private static final Logger logger = LoggerFactory.getLogger(PeerEurekaNodes.class);
    protected final PeerAwareInstanceRegistry registry;
    protected final EurekaServerConfig serverConfig;
    protected final EurekaClientConfig clientConfig;
    protected final ServerCodecs serverCodecs;
    private final ApplicationInfoManager applicationInfoManager;
    private volatile List<PeerEurekaNode> peerEurekaNodes = Collections.emptyList();
    private volatile Set<String> peerEurekaNodeUrls = Collections.emptySet();
    private ScheduledExecutorService taskExecutor;

    @Inject
    public PeerEurekaNodes(PeerAwareInstanceRegistry registry, EurekaServerConfig serverConfig, EurekaClientConfig clientConfig, ServerCodecs serverCodecs, ApplicationInfoManager applicationInfoManager) {
        this.registry = registry;
        this.serverConfig = serverConfig;
        this.clientConfig = clientConfig;
        this.serverCodecs = serverCodecs;
        this.applicationInfoManager = applicationInfoManager;
    }

    public List<PeerEurekaNode> getPeerNodesView() {
        return Collections.unmodifiableList(this.peerEurekaNodes);
    }

    public List<PeerEurekaNode> getPeerEurekaNodes() {
        return this.peerEurekaNodes;
    }

    public int getMinNumberOfAvailablePeers() {
        return this.serverConfig.getHealthStatusMinNumberOfAvailablePeers();
    }

    public void start() {
        this.taskExecutor = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
            public Thread newThread(Runnable r) {
                Thread thread = new Thread(r, "Eureka-PeerNodesUpdater");
                thread.setDaemon(true);
                return thread;
            }
        });

        try {
            this.updatePeerEurekaNodes(this.resolvePeerUrls());
            Runnable peersUpdateTask = new Runnable() {
                public void run() {
                    try {
                        PeerEurekaNodes.this.updatePeerEurekaNodes(PeerEurekaNodes.this.resolvePeerUrls());
                    } catch (Throwable var2) {
                        PeerEurekaNodes.logger.error("Cannot update the replica Nodes", var2);
                    }

                }
            };
            this.taskExecutor.scheduleWithFixedDelay(peersUpdateTask, (long)this.serverConfig.getPeerEurekaNodesUpdateIntervalMs(), (long)this.serverConfig.getPeerEurekaNodesUpdateIntervalMs(), TimeUnit.MILLISECONDS);
        } catch (Exception var3) {
            throw new IllegalStateException(var3);
        }

        Iterator var4 = this.peerEurekaNodes.iterator();

        while(var4.hasNext()) {
            PeerEurekaNode node = (PeerEurekaNode)var4.next();
            logger.info("Replica node URL:  {}", node.getServiceUrl());
        }

    }

    public void shutdown() {
        this.taskExecutor.shutdown();
        List<PeerEurekaNode> toRemove = this.peerEurekaNodes;
        this.peerEurekaNodes = Collections.emptyList();
        this.peerEurekaNodeUrls = Collections.emptySet();
        Iterator var2 = toRemove.iterator();

        while(var2.hasNext()) {
            PeerEurekaNode node = (PeerEurekaNode)var2.next();
            node.shutDown();
        }

    }

    protected List<String> resolvePeerUrls() {
        InstanceInfo myInfo = this.applicationInfoManager.getInfo();
        String zone = InstanceInfo.getZone(this.clientConfig.getAvailabilityZones(this.clientConfig.getRegion()), myInfo);
        List<String> replicaUrls = EndpointUtils.getDiscoveryServiceUrls(this.clientConfig, zone, new InstanceInfoBasedUrlRandomizer(myInfo));
        int idx = 0;

        while(idx < replicaUrls.size()) {
            if (this.isThisMyUrl((String)replicaUrls.get(idx))) {
                replicaUrls.remove(idx);
            } else {
                ++idx;
            }
        }

        return replicaUrls;
    }

    protected void updatePeerEurekaNodes(List<String> newPeerUrls) {
        if (newPeerUrls.isEmpty()) {
            logger.warn("The replica size seems to be empty. Check the route 53 DNS Registry");
        } else {
            Set<String> toShutdown = new HashSet(this.peerEurekaNodeUrls);
            toShutdown.removeAll(newPeerUrls);
            Set<String> toAdd = new HashSet(newPeerUrls);
            toAdd.removeAll(this.peerEurekaNodeUrls);
            if (!toShutdown.isEmpty() || !toAdd.isEmpty()) {
                List<PeerEurekaNode> newNodeList = new ArrayList(this.peerEurekaNodes);
                if (!toShutdown.isEmpty()) {
                    logger.info("Removing no longer available peer nodes {}", toShutdown);
                    int i = 0;

                    while(i < newNodeList.size()) {
                        PeerEurekaNode eurekaNode = (PeerEurekaNode)newNodeList.get(i);
                        if (toShutdown.contains(eurekaNode.getServiceUrl())) {
                            newNodeList.remove(i);
                            eurekaNode.shutDown();
                        } else {
                            ++i;
                        }
                    }
                }

                if (!toAdd.isEmpty()) {
                    logger.info("Adding new peer nodes {}", toAdd);
                    Iterator var7 = toAdd.iterator();

                    while(var7.hasNext()) {
                        String peerUrl = (String)var7.next();
                        newNodeList.add(this.createPeerEurekaNode(peerUrl));
                    }
                }

                this.peerEurekaNodes = newNodeList;
                this.peerEurekaNodeUrls = new HashSet(newPeerUrls);
            }
        }
    }

    protected PeerEurekaNode createPeerEurekaNode(String peerEurekaNodeUrl) {
        HttpReplicationClient replicationClient = JerseyReplicationClient.createReplicationClient(this.serverConfig, this.serverCodecs, peerEurekaNodeUrl);
        String targetHost = hostFromUrl(peerEurekaNodeUrl);
        if (targetHost == null) {
            targetHost = "host";
        }

        return new PeerEurekaNode(this.registry, targetHost, peerEurekaNodeUrl, replicationClient, this.serverConfig);
    }

    /** @deprecated */
    public static boolean isThisMe(String url) {
        InstanceInfo myInfo = ApplicationInfoManager.getInstance().getInfo();
        String hostName = hostFromUrl(url);
        return hostName != null && hostName.equals(myInfo.getHostName());
    }

    public boolean isThisMyUrl(String url) {
        String myUrlConfigured = this.serverConfig.getMyUrl();
        return myUrlConfigured != null ? myUrlConfigured.equals(url) : this.isInstanceURL(url, this.applicationInfoManager.getInfo());
    }

    public boolean isInstanceURL(String url, InstanceInfo instance) {
        String hostName = hostFromUrl(url);
        String myInfoComparator = instance.getHostName();
        if (this.clientConfig.getTransportConfig().applicationsResolverUseIp()) {
            myInfoComparator = instance.getIPAddr();
        }

        return hostName != null && hostName.equals(myInfoComparator);
    }

    public static String hostFromUrl(String url) {
        URI uri;
        try {
            uri = new URI(url);
        } catch (URISyntaxException var3) {
            logger.warn("Cannot parse service URI {}", url, var3);
            return null;
        }

        return uri.getHost();
    }
}
